import random

# 账户类，每条数据表示一个用户（卡）
class User:
    def __init__(self, name, num, phone, money, password, card):
        # 公开的实例属性
        self.name = name  # 用户的姓名
        self.num = num  # 用户的身份证号
        self.phone = phone  # 用户的手机号
        self.money = money  # 用户的当前余额
        self.password = password  # 卡的密码
        self.card = card  # 卡号
        self.error_count = 0  # 当前卡的密码错误次数 0-3
        self.status = True  # 卡的状态，True：启用；False：锁定

# 使用字段来存储用户卡，key：身份证号，value：卡的对象
account_dict = {
    '420581001': User('张三', '420581001', '13355556666',
                      3000.0, '987654', '888888'),
    '420581002': User('李四', '420581002', '13355556666',
                      2000.0, '123456', '666666')
}

# 显示欢迎信息
def print_welcome():
    print('*' * 43)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 3, ' ' * 8, '欢迎登录银行管理系统', ' ' * 8, '*' * 3)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 43)

# 显示所有的功能项
def show_options():
    print('*' * 43)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 3, ' ' * 5, '1.开户(1)      2.查询(2)', ' ' * 5, '*' * 3)
    print('*' * 3, ' ' * 5, '3.取款(3)      4.存款(4)', ' ' * 5, '*' * 3)
    print('*' * 3, ' ' * 5, '5.转账(5)      6.锁定(6)', ' ' * 5, '*' * 3)
    print('*' * 3, ' ' * 5, '7.解锁(7)               ', ' ' * 5, '*' * 3)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 3, ' ' * 5, '退出(0)                 ', ' ' * 5, '*' * 3)
    print('*' * 3, ' ' * 35, '*' * 3)
    print('*' * 43)

# 判断卡号是否已经存在
def card_exist(card):
    # 根据推导式获取所有卡号的列表数据
    # key是推导式循环时的身份证号，value是循环时的用户对象
    card_list = [value.card for key, value in account_dict.items()]
    return card in card_list  # card是否在card_list中

# 根据卡号获取用户对象
def query_account(card):
    for key, value in account_dict.items():  # value就是用户对象
        if value.card == card:
            return value
    # 程序走到这里？表示循环结束都没有符合的卡号
    return None  # 没找到

# 生成6位数字的卡号，不能是已经存在的卡号
def random_card():
    card = ''
    for i in range(6):
        card += str(random.randrange(0, 10))  # 包含0，不包含10
    # 判断account_dict中是否已经有了这个卡号
    if card_exist(card):  # 存在
        return random_card()  # 递归
    else:  # 不存在
        return card

# 开户
def open_account():
    # 输入
    name = input('请输入开户用户的姓名：')
    num = input('请输入开户用户的身份证号：')  # 判断重复
    phone = input('请输入开户用户的手机号：')
    money = float(input('请输入预存金额：'))  # 这个可以不用校验
    password = input('请输入卡的密码：')
    # 校验
    if name == '' or num == '' or phone == '' or password == '':
        print('输入的信息有误...')
        return
    # 校验身份证号是否已经存在
    if num in account_dict.keys():
        print('该用户已经开户...')
        return
    # 生成卡号，不能是已经存在的卡号
    card = random_card()
    user = User(name, num, phone, money, password, card)
    # 添加
    account_dict[num] = user
    print(f'开户成功，当前有{len(account_dict)}个用户')

# 查询余额
def query():
    card = input('请输入卡号：')
    user = query_account(card)
    if user is None:  # 不存在
        print('卡号错误...')
        return
    # 判断是否被锁定
    if not user.status:
        print(f'您好，卡{user.card}已经被锁定，请先解锁...')
        return
    while True:
        password = input('请输入密码：')
        if password == user.password:
            # 卡密正确，错误次数归零
            user.error_count = 0
            print(f'姓名：{user.name}, 卡号：{user.card}, 余额：{user.money}')
            return
        else:
            user.error_count += 1
            print(f'密码错误，当前已经错误{user.error_count}次，达到3次将锁定账户')
            if user.error_count >= 3:
                user.status = False  # 锁卡
                print(f'您已经输入密码错误3次，卡{card}已被锁定')
                return
            else:
                continue

# 取款
def get_money():
    card = input('请输入卡号：')
    user = query_account(card)
    if user is None:  # 不存在
        print('卡号错误...')
        return
    # 判断是否被锁定
    if not user.status:
        print(f'您好，卡{user.card}已经被锁定，请先解锁...')
        return
    while True:
        password = input('请输入密码：')
        if password == user.password:
            # 卡密正确，错误次数归零
            user.error_count = 0
            # 取款操作
            mon = float(input('请输入取款金额：'))
            if 0 < mon <= user.money:
                user.money -= mon
                print(f'姓名：{user.name}, 卡号：{user.card}, 取款：{mon}，余额：{user.money}')
            else:
                print('输入的金额有误，程序已退出')
            return
        else:
            user.error_count += 1
            print(f'密码错误，当前已经错误{user.error_count}次，达到3次将锁定账户')
            if user.error_count >= 3:
                user.status = False  # 锁卡
                print(f'您已经输入密码错误3次，卡{card}已被锁定')
                return
            else:
                continue

# 存款
def add_money():
    card = input('请输入卡号：')
    user = query_account(card)
    if user is None:  # 不存在
        print('卡号错误...')
        return
    # 判断是否被锁定
    if not user.status:
        print(f'您好，卡{user.card}已经被锁定，请先解锁...')
        return
    while True:
        password = input('请输入密码：')
        if password == user.password:
            # 卡密正确，错误次数归零
            user.error_count = 0
            # 取款操作
            mon = float(input('请输入存款金额：'))
            if 0 < mon:
                user.money += mon
                print(f'姓名：{user.name}, 卡号：{user.card}, 存款：{mon}，余额：{user.money}')
            else:
                print('输入的金额有误，程序已退出')
            return
        else:
            user.error_count += 1
            print(f'密码错误，当前已经错误{user.error_count}次，达到3次将锁定账户')
            if user.error_count >= 3:
                user.status = False  # 锁卡
                print(f'您已经输入密码错误3次，卡{card}已被锁定')
                return
            else:
                continue

# 转账
def transfer_money():
    card_out = input('请输入转出的卡号：')
    user_out = query_account(card_out)
    if user_out is None:  # 不存在
        print('转出的卡号错误...')
        return
    # 判断是否被锁定
    if not user_out.status:
        print(f'您好，卡{user_out.card}已经被锁定，请先解锁...')
        return
    card_in = input('请输入转入的卡号：')
    user_in = query_account(card_in)
    if user_in is None:
        print('转入的卡号错误...')
        return
    # 验证转出的卡的密码
    while True:
        password = input('请输入密码：')
        if password == user_out.password:
            # 卡密正确，错误次数归零
            user_out.error_count = 0
            # 转账操作
            mon = float(input('请输入转账金额：'))
            if 0 < mon <= user_out.money:
                check = input(f'提示：{card_out}正在向{card_in}转入资金，金额{mon}，确认无误后回复y/Y：')
                if check == 'y' or check == 'Y':
                    # 资金变动
                    user_in.money += mon
                    user_out.money -= mon
                    print(f'姓名：{user_out.name}, 卡号：{card_out}, 转款：{mon}，余额：{user_out.money}')
                else:
                    print('取消转账，请重新操作...')
            else:
                print('输入的金额有误，程序已退出')
            return
        else:
            user_out.error_count += 1
            print(f'密码错误，当前已经错误{user_out.error_count}次，达到3次将锁定账户')
            if user_out.error_count >= 3:
                user_out.status = False  # 锁卡
                print(f'您已经输入密码错误3次，卡{card_out}已被锁定')
                return
            else:
                continue

# 锁卡
def lock_account():
    card = input('请输入锁定的卡号：')
    user = query_account(card)
    if user is None:
        print('卡号错误')
    else:
        user.status = False
        print(f'卡{card}已经被锁定')

# 解锁
def unlock_account():
    card = input('请输入解锁的卡号：')
    user = query_account(card)
    if user is None:
        print('卡号错误')
    else:
        user.error_count = 0
        user.status = True
        print(f'卡{card}已经解锁成功，现在可以使用查询、取款、存款、转账等操作')

# 程序的入口
def main():
    # 打印欢迎信息
    print_welcome()
    # 表示程序的运行状态
    flag = True
    while flag:
        username = input('请输入管理员账户：')
        if username != 'admin':
            print('管理员账号输入有误...')
            continue
        password = input('请输入密码：')
        if password != '12345':
            print('密码输入错误...')
            continue
        # 程序走到这里，相当于成功登录了
        print('登录成功，请稍后...')
        while flag:
            show_options()
            option = input('请选择功能项：')
            print('-' * 40)
            if option == '1':
                open_account()
            elif option == '2':
                query()
            elif option == '3':
                get_money()
            elif option == '4':
                add_money()
            elif option == '5':
                transfer_money()
            elif option == '6':
                lock_account()
            elif option == '7':
                unlock_account()
            elif option == '0':
                print('退出，欢迎再次使用...')
                # 退出的本质是结束循环，2个循环，结束哪个？
                flag = False # 控制了2层循环的条件
            else:
                print('输入有误，请重新选择')
            print('-' * 40)

# 程序开始
main()